package com.newcoin.xgb.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.newcoin.xgb.dto.*;
import com.newcoin.xgb.entity.*;
import com.newcoin.xgb.mapper.*;
import com.newcoin.xgb.po.ShipAddressPo;
import com.newcoin.xgb.po.TeamMemberPo;
import com.newcoin.xgb.po.TeamReportPo;
import com.newcoin.xgb.service.XgbAccountService;
import com.newcoin.xgb.service.XgbUserService;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

@Service
@Slf4j
public class XgbUserServiceImpl implements XgbUserService {

    @Autowired
    private UsersMapper mapper;

    @Autowired
    private ShipAddressMapper shipAddressMapper;

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private BankMapper bankMapper;

    @Autowired
    private CommonMapper commonMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private XgbAccountService service;

    @Autowired
    private XgbBankMapper xgbBankMapper;

    @Autowired
    private XgbUserBankMapper xgbUserBankMapper;

    @Value("${defaultHeadPath}")
    private String defaultHeadPath;

    @Value("${filePath}")
    private String filePath;

    @Value("${webRegistered}")
    private String webRegistered;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result registered(RegisteredDto registeredDto) throws Exception {
        log.info("registeredDto={}", registeredDto);
        String redisCode = redisTemplate.opsForValue().get("send" + registeredDto.getMobile());
        Result result = new Result();
        if (StringUtils.isEmpty(redisCode)) {
            result.setCode(500);
            result.setMessage("验证码不存在");
            return result;
        }
        if (!redisCode.equalsIgnoreCase(registeredDto.getVerCode())) {
            result.setCode(500);
            result.setMessage("验证码不正确");
            return result;
        }
        QueryWrapper<XgbUsers> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", registeredDto.getMobile());
        XgbUsers users = mapper.selectOne(queryWrapper);
        if (users != null) {
            result.setCode(500);
            result.setMessage("该号码已注册");
            return result;
        }
        users = new XgbUsers();
        users.setInvCode(createInviteCode());
        users.setLoginPwd(DigestUtils.md5DigestAsHex(registeredDto.getPassword().getBytes()));
        users.setMobile(registeredDto.getMobile());
        users.setNickname(registeredDto.getMobile());
        users.setHeadPath(defaultHeadPath);
        if (!StringUtils.isEmpty(registeredDto.getInvCode())) {
            QueryWrapper<XgbUsers> pQueryWrapper = new QueryWrapper<>();
            pQueryWrapper.eq("inv_code", registeredDto.getInvCode());
            XgbUsers pUser = mapper.selectOne(pQueryWrapper);
            if (pUser == null) {
                result.setCode(500);
                result.setMessage("推荐人不存在");
                return result;
            }
            users.setPid(pUser.getId());
            users.setPath(pUser.getPath() + "," + pUser.getId());
            XgbUsers finalUsers = users;
            UpdateWrapper<XgbUsers> usersUpdateWrapper = new UpdateWrapper<>();
            usersUpdateWrapper.eq("id", pUser.getId()).setSql("direct_push_num=direct_push_num+1");
            int row = mapper.update(null, usersUpdateWrapper);
            log.info("增加直推人数:" + row);
            UpdateWrapper<XgbUsers> usersUpdateWrapper1 = new UpdateWrapper<>();
            usersUpdateWrapper1.setSql("team_num=team_num+1")
                    .last("WHERE id IN (" + finalUsers.getPath() + ")");
            row = row + mapper.update(null, usersUpdateWrapper1);
            log.info("增加团队人数:" + --row);//(row-1)
        }
        users.setRegDate(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date()));
        int row = mapper.insert(users);
        row = row + service.createAccount(users.getId());
        if (row != 2) {
            result.setMessage("注册失败");
            result.setCode(500);
            return result;
        }
        result.setCode(200);
        result.setMessage("注册成功");
        return result;
    }

    @Override
    public Result<XgbUsers> login(LoginDto loginDto) throws Exception {
        log.info("loginDto={}", loginDto);
        Result<XgbUsers> result = new Result<>();
        QueryWrapper<XgbUsers> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("mobile", loginDto.getMobile()).eq("login_pwd", DigestUtils.md5DigestAsHex(loginDto.getPassword().getBytes()));
        XgbUsers users = mapper.selectOne(queryWrapper);
        if (users == null) {
            result.setCode(500);
            result.setMessage("手机号或密码错误");
            return result;
        }
        if (users.getState() == 1) {
            result.setCode(500);
            result.setMessage("您的账号已被冻结");
            return result;
        }
        String loginDate = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date());
        users.setLoginDate(loginDate);
        UpdateWrapper<XgbUsers> usersUpdateWrapper = new UpdateWrapper<>();
        usersUpdateWrapper.eq("id", users.getId()).set("login_date", loginDate);
        mapper.update(null, usersUpdateWrapper);
        String token = makeToken();
        redisTemplate.opsForValue().set("token:" + users.getId(), token);
        users.setToken(token);
        result.setCode(200);
        result.setMessage("登录成功");
        result.setData(users);
        return result;
    }

    @Override
    public Result outLogin(Long userId) throws Exception {
        log.info("outLogin={}", userId);
        redisTemplate.delete("token:" + userId);
        Result result = new Result();
        result.setMessage("退出成功");
        result.setCode(200);
        return result;
    }

    @Override
    public Result changeHead(String path, Long userId) throws Exception {
        log.info("path={},userId={}", path, userId);
        Result result = new Result();
        UpdateWrapper<XgbUsers> usersUpdateWrapper = new UpdateWrapper<>();
        usersUpdateWrapper.eq("id", userId).set("head_path", path);
        int row = mapper.update(null, usersUpdateWrapper);
        if (row != 1) {
            result.setCode(500);
            result.setMessage("修改头像失败");
            return result;
        }
        result.setCode(200);
        result.setMessage("修改成功");
        return result;
    }

    @Override
    public Result changeNickName(ChangeNicknameDto changeNicknameDto) throws Exception {
        log.info("changeNicknameDto={}", changeNicknameDto);
        Result result = new Result();
        UpdateWrapper<XgbUsers> usersUpdateWrapper = new UpdateWrapper<>();
        usersUpdateWrapper.eq("id", changeNicknameDto.getUserId()).set("nickname", changeNicknameDto.getNickname());
        int row = mapper.update(null, usersUpdateWrapper);
        if (row != 1) {
            result.setMessage("修改失败");
            result.setCode(500);
            return result;
        }
        result.setMessage("修改成功");
        result.setCode(200);
        return result;
    }

    @Override
    public Result changePassword(ChangePasswordDto changePasswordDto) throws Exception {
        log.info("changePasswordDto={}", changePasswordDto);
        Result result = new Result();
        if (loginVerification(changePasswordDto.getUserId(), changePasswordDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        String redisCode = redisTemplate.opsForValue().get("send" + changePasswordDto.getMobile());
        if (!redisCode.equalsIgnoreCase(changePasswordDto.getVerCode())) {
            result.setCode(500);
            result.setMessage("验证码不正确");
            return result;
        }
        UpdateWrapper<XgbUsers> usersUpdateWrapper = new UpdateWrapper<>();
        usersUpdateWrapper.eq("id", changePasswordDto.getUserId()).set(changePasswordDto.getType() == 0 ? "login_pwd" : "pay_pwd", DigestUtils.md5DigestAsHex(changePasswordDto.getNewPwd().getBytes()));
        int row = mapper.update(null, usersUpdateWrapper);
        if (row != 1) {
            result.setCode(500);
            result.setMessage(changePasswordDto.getType() == 0 ? "修改登录密码失败" : "修改支付密码失败");
            return result;
        }
        result.setCode(200);
        result.setMessage(changePasswordDto.getType() == 0 ? "修改登录密码成功" : "修改支付密码成功");
        return result;
    }

    @Override
    public Result forgetPassword(ForgetPasswordDto forgetPasswordDto) throws Exception {
        log.info("forgetPasswordDto={}", forgetPasswordDto);
        Result result = new Result();
        String redisCode = redisTemplate.opsForValue().get("send" + forgetPasswordDto.getMobile());
        if (!StringUtils.isEmpty(redisCode) && redisCode.equalsIgnoreCase(forgetPasswordDto.getVerCode())) {
            UpdateWrapper<XgbUsers> usersUpdateWrapper = new UpdateWrapper<>();
            usersUpdateWrapper.eq("mobile", forgetPasswordDto.getMobile()).set("login_pwd", DigestUtils.md5DigestAsHex(forgetPasswordDto.getNewPwd().getBytes()));
            int row = mapper.update(null, usersUpdateWrapper);
            if (row != 1) {
                result.setCode(500);
                result.setMessage("重置密码失败");
                return result;
            }
            result.setCode(200);
            result.setMessage("重置密码成功");
            return result;
        }
        result.setCode(500);
        result.setMessage("验证码不正确");
        return result;
    }

    @Override
    public Result addShipAddress(AddShipAddressDto addShipAddressDto) throws Exception {
        log.info("addShipAddressDto={}", addShipAddressDto);
        Result result = new Result();
        if (loginVerification(addShipAddressDto.getUserId(), addShipAddressDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbShipAddress shipAddress = new XgbShipAddress();
        if (addShipAddressDto.getIsDefault()) {
            QueryWrapper<XgbShipAddress> shipAddressQueryWrapper = new QueryWrapper<>();
            shipAddressQueryWrapper.eq("user_id", addShipAddressDto.getUserId()).eq("is_default", 1);
            XgbShipAddress defaultAddress = shipAddressMapper.selectOne(shipAddressQueryWrapper);
            if (defaultAddress != null) {
                UpdateWrapper<XgbShipAddress> shipAddressUpdateWrapper = new UpdateWrapper<>();
                shipAddressUpdateWrapper.eq("id", defaultAddress.getId()).set("is_default", 0);
                int row = shipAddressMapper.update(null, shipAddressUpdateWrapper);
                log.info("修改之前的默认地址={}", row == 1 ? "成功" : "失败");
            }
            shipAddress.setIsDefault(addShipAddressDto.getIsDefault());
        } else {
            int count = shipAddressMapper.selectCount(new QueryWrapper<XgbShipAddress>().eq("user_id", addShipAddressDto.getUserId()));
            if (count == 0) {
                shipAddress.setIsDefault(true);
            }
        }
        shipAddress.setUserId(addShipAddressDto.getUserId());
        shipAddress.setName(addShipAddressDto.getName());
        shipAddress.setMobile(addShipAddressDto.getMobile());
        shipAddress.setPostalCode(addShipAddressDto.getPostalCode());
        shipAddress.setArea(addShipAddressDto.getArea());
        shipAddress.setAddress(addShipAddressDto.getAddress());
        int row = shipAddressMapper.insert(shipAddress);
        if (row != 1) {
            result.setCode(500);
            result.setMessage("添加收货地址失败");
            return result;
        }
        result.setCode(200);
        result.setMessage("添加收货地址成功");
        return result;
    }

    @Override
    public Result<ShipAddressPo> getShipAddress(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result<ShipAddressPo> result = new Result<>();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        QueryWrapper<XgbShipAddress> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", queryParameterDto.getUserId()).orderByAsc("id");
        Page<XgbShipAddress> page = new Page<>();
        page.setCurrent(queryParameterDto.getPage());
        page.setSize(10);
        IPage<XgbShipAddress> iPage = shipAddressMapper.selectPage(page, queryWrapper);
        ShipAddressPo shipAddressPo = new ShipAddressPo();
        shipAddressPo.setCurrentPage(iPage.getCurrent());
        shipAddressPo.setTotalPages(iPage.getPages());
        shipAddressPo.setList(iPage.getRecords());
        result.setCode(200);
        result.setMessage("成功");
        result.setData(shipAddressPo);
        return result;
    }

    @Override
    public Result<XgbShipAddress> getShipAddressById(QueryShipAddressById queryShipAddressById) throws Exception {
        log.info("queryParameterDto={}", queryShipAddressById);
        Result<XgbShipAddress> result = new Result<>();
        if (loginVerification(queryShipAddressById.getUserId(), queryShipAddressById.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbShipAddress xgbShipAddress = shipAddressMapper.selectById(queryShipAddressById.getId());
        result.setMessage("获取成功");
        result.setCode(200);
        result.setData(xgbShipAddress);
        return result;
    }

    @Override
    public Result changeShipAddress(ChangeShipAddressDto changeShipAddressDto) throws Exception {
        log.info("changeShipAddressDto={}", changeShipAddressDto);
        Result result = new Result();
        if (loginVerification(changeShipAddressDto.getUserId(), changeShipAddressDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        if (!changeShipAddressDto.getIsDefault()) {
            XgbShipAddress shipAddress = shipAddressMapper.selectById(changeShipAddressDto.getId());
            if (shipAddress.getIsDefault()) {
                result.setCode(500);
                result.setMessage("默认地址不可改为非默认,若替换默认地址直接将其他地址设为默认即可");
                return result;
            }
        }
        if (changeShipAddressDto.getIsDefault()) {
            QueryWrapper<XgbShipAddress> shipAddressQueryWrapper = new QueryWrapper<>();
            shipAddressQueryWrapper.eq("user_id", changeShipAddressDto.getUserId()).eq("is_default", 1);
            XgbShipAddress defaultAddress = shipAddressMapper.selectOne(shipAddressQueryWrapper);
            if (defaultAddress != null) {
                UpdateWrapper<XgbShipAddress> shipAddressUpdateWrapper = new UpdateWrapper<>();
                shipAddressUpdateWrapper.eq("id", defaultAddress.getId()).set("is_default", 0);
                int row = shipAddressMapper.update(null, shipAddressUpdateWrapper);
                log.info("修改地址方法:修改之前的默认地址={}", row == 1 ? "成功" : "失败");
            }
        }
        XgbShipAddress xgbShipAddress = new XgbShipAddress();
        xgbShipAddress.setUserId(changeShipAddressDto.getUserId());
        xgbShipAddress.setId(changeShipAddressDto.getId());
        xgbShipAddress.setAddress(changeShipAddressDto.getAddress());
        xgbShipAddress.setArea(changeShipAddressDto.getArea());
        xgbShipAddress.setPostalCode(changeShipAddressDto.getPostalCode());
        xgbShipAddress.setMobile(changeShipAddressDto.getMobile());
        xgbShipAddress.setName(changeShipAddressDto.getName());
        xgbShipAddress.setIsDefault(changeShipAddressDto.getIsDefault());
        int row = shipAddressMapper.updateById(xgbShipAddress);
        if (row != 1) {
            result.setCode(500);
            result.setMessage("修改地址失败");
            return result;
        }
        result.setCode(200);
        result.setMessage("修改地址成功");
        return result;
    }

    @Override
    public Result deleteShipAddress(QueryParameterDto queryParameterDto) throws Exception {
        log.info("queryParameterDto={}", queryParameterDto);
        Result result = new Result();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        QueryWrapper<XgbShipAddress> shipAddressQueryWrapper = new QueryWrapper<>();
        shipAddressQueryWrapper.eq("id", queryParameterDto.getId());
        XgbShipAddress xgbShipAddress = shipAddressMapper.selectById(queryParameterDto.getId());
        if (xgbShipAddress.getIsDefault()) {
            result.setCode(500);
            result.setMessage("默认地址不可删除");
            return result;
        }
        int row = shipAddressMapper.deleteById(queryParameterDto.getId());
        if (row != 1) {
            result.setCode(500);
            result.setMessage("地址删除失败");
            return result;
        }
        result.setCode(200);
        result.setMessage("地址删除成功");
        return result;
    }

    @Override
    public Result<TeamReportPo> getTeamReport(QueryParameterDto queryParameterDto) throws Exception {
        log.info("changeBankDto={}", queryParameterDto);
        Result<TeamReportPo> result = new Result();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbUsers users = mapper.selectById(queryParameterDto.getUserId());
        String teamUserId = mapper.getTeamUserId("'%" + users.getPath() + "%'");
        XgbAccount account = accountMapper.selectOne(new QueryWrapper<XgbAccount>()
                .eq("user_id", queryParameterDto.getUserId()));
        BigDecimal teamTotalFinancialBalance = accountMapper.getTeamFinancialBalance("IN (" + teamUserId + ")");
        BigDecimal teamBalance = accountMapper.getTeamBalance("IN (" + teamUserId + ")");
        Integer teamEffective = mapper.getTeamEffectiveCount("'%" + users.getPath() + "%'");
        TeamReportPo reportPo = new TeamReportPo();
        reportPo.setTeamNum(users.getTeamNum());
        reportPo.setTeamEffectiveNum(teamEffective);
        reportPo.setTeamTotalRecharge(account.getTeamTotalRecharge());
        reportPo.setTeamTotalWithdrawal(account.getTeamTotalWithdrawal());
        reportPo.setTeamTotalBalance(teamBalance);
        reportPo.setTeamTotalFinancialBalance(teamTotalFinancialBalance);
        result.setMessage("成功");
        result.setCode(200);
        result.setData(reportPo);
        return result;
    }

    @Override
    public Result<TeamMemberPo> getTeamMember(QueryParameterDto queryParameterDto) throws Exception {
        log.info("changeBankDto={}", queryParameterDto);
        Result<TeamMemberPo> result = new Result();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbUsers user = mapper.selectById(queryParameterDto.getUserId());
        Page<XgbUsers> page = new Page<>();
        page.setSize(10);
        page.setCurrent(queryParameterDto.getPage());
        IPage<XgbUsers> iPage = null;
        switch (queryParameterDto.getType()) {
            case 1:
                iPage = mapper.getDirectPushUser(page, user.getId());
                break;
            case 2:
                String directPushUserId1 = mapper.getDirectPushUserId(user.getId());
                String secondFloorUserId1 = mapper.getSecondFloorUserId("IN (" + directPushUserId1 + ")");
                iPage = mapper.getUserList(page, "IN (" + secondFloorUserId1 + ")");
                break;
            case 3:
                String directPushUserId2 = mapper.getDirectPushUserId(user.getId());
                String secondFloorUserId2 = mapper.getSecondFloorUserId("IN (" + directPushUserId2 + ")");
                String teamUserId = mapper.getThreeLayers("IN (" + secondFloorUserId2 + ")");
                iPage = mapper.getUserList(page, "IN (" + teamUserId + ")");
                break;
            default:
                iPage = mapper.getDirectPushUser(page, user.getId());
                break;
        }
        XgbAccount account = accountMapper.selectOne(new QueryWrapper<XgbAccount>()
                .eq("user_id", queryParameterDto.getUserId()));
        TeamMemberPo teamMemberPo = new TeamMemberPo();
        teamMemberPo.setCurrentPage(iPage.getCurrent());
        teamMemberPo.setTotalPages(iPage.getPages());
        teamMemberPo.setList(iPage.getRecords());
        result.setCode(200);
        result.setMessage("成功");
        result.setData(teamMemberPo);
        return result;
    }

    @Override
    public Result<Boolean> isSettingPayPwd(QueryParameterDto queryParameterDto) throws Exception {
        log.info("changeBankDto={}", queryParameterDto);
        Result<Boolean> result = new Result();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbUsers users = mapper.selectById(queryParameterDto.getUserId());
        if (users.getPayPwd() == null) {
            result.setCode(200);
            result.setMessage("未设置支付密码");
            result.setData(false);
            return result;
        }
        result.setCode(200);
        result.setMessage("已设置支付密码");
        result.setData(true);
        return result;
    }

    @Override
    public Result<String> getInvCodePath(QueryParameterDto queryParameterDto) throws Exception {
        log.info("changeBankDto={}", queryParameterDto);
        Result<String> result = new Result();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbUsers users = mapper.selectById(queryParameterDto.getUserId());
        if (users.getIvnCodePath() == null) {
//            String file1 = filePath + "/base/base.png";
//            String file2 = filePath + "/qrcode/" + queryParameterDto.getUserId() + ".png";
//            String imgName = System.currentTimeMillis() + "-" + queryParameterDto.getUserId() + ".png";
//            String savePath = filePath + "/invImg/" + imgName;
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(webRegistered + "/web/registered?invCode=" + users.getInvCode(), BarcodeFormat.QR_CODE, 350, 350);
            bitMatrix = deleteWhite(bitMatrix);
            Path path = FileSystems.getDefault().getPath(filePath + "qrcode/" + queryParameterDto.getUserId() + ".png");
            MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path);
//            BufferedImage bufferedImage1 = getBufferedImage(file1);
//            BufferedImage bufferedImage2 = getBufferedImage(file2);
//            BufferedImage buffImg = overlyingImage(bufferedImage1, bufferedImage2, 240, 750, 1.0f);
//            drawProductText(users.getInvCode(), buffImg);
//            generateSaveFile(buffImg, savePath);
            int row = mapper.update(null, new UpdateWrapper<XgbUsers>()
                    .eq("id", users.getId())
                    .set("ivn_code_path", "/static/qrcode/" + queryParameterDto.getUserId() + ".png"));
            if (row != 1) {
                result.setCode(500);
                result.setMessage("获取分享海报失败");
                return result;
            }
            result.setCode(200);
            result.setMessage("成功");
            result.setData("/static/qrcode/" + queryParameterDto.getUserId() + ".png");
            return result;
        }
        result.setCode(200);
        result.setMessage("成功");
        result.setData(users.getIvnCodePath());
        return result;
    }

    @Override
    public Result<Boolean> isBindReceiptAddress(QueryParameterDto queryParameterDto) throws Exception {
        log.info("changeBankDto={}", queryParameterDto);
        Result<Boolean> result = new Result();
        if (loginVerification(queryParameterDto.getUserId(), queryParameterDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        XgbShipAddress xgbShipAddress = shipAddressMapper.selectOne(new QueryWrapper<XgbShipAddress>().eq("user_id", queryParameterDto.getUserId()).last("limit 1"));
        if (xgbShipAddress == null) {
            result.setCode(200);
            result.setMessage("未添加收货地址");
            result.setData(false);
            return result;
        }
        result.setCode(200);
        result.setMessage("已添加收货地址");
        result.setData(true);
        return result;
    }

    @Override
    public Result verified(VerifiedDto verifiedDto) throws Exception {
        log.info("verifiedDto={}", verifiedDto);
        Result result = new Result();
        if (loginVerification(verifiedDto.getUserId(), verifiedDto.getToken())) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "APPCODE 8de12efaf91442708b06f656448f6a1f");
        HttpEntity<String> httpEntity = new HttpEntity(null, headers);
        ResponseEntity<String> str = restTemplate.exchange("http://idcard3.market.alicloudapi.com/idcardAudit?idcard=" + verifiedDto.getIdCard() + "&name=" + verifiedDto.getName(), HttpMethod.GET, httpEntity, String.class);
        JSONObject res = JSON.parseObject(str.getBody());
        log.info(res.toJSONString());
        String code = String.valueOf(res.get("showapi_res_code"));
        if (code.equalsIgnoreCase("0")) {
            log.info(res.get("showapi_res_body").toString());
            Map<String, Object> resMap = (Map<String, Object>) res.get("showapi_res_body");
            if ((int) resMap.get("code") == 1) {
                result.setCode(500);
                result.setMessage("身份证号码姓名不匹配");
                return result;
            } else if ((int) resMap.get("code") == 101) {
                result.setCode(500);
                result.setMessage("验证信息重复输入，避免恶意验证请间隔60秒以上再次核验");
                return result;
            } else if ((int) resMap.get("code") == 0) {
                int row = mapper.update(null, new UpdateWrapper<XgbUsers>()
                        .eq("id", verifiedDto.getUserId())
                        .set("real_name", verifiedDto.getName())
                        .set("is_real_name", 1)
                        .set("id_card", verifiedDto.getIdCard()));
                if (row != 1) {
                    result.setCode(500);
                    result.setMessage("实名失败");
                    return result;
                }
                result.setCode(200);
                result.setMessage("成功");
                return result;
            }
            result.setCode(500);
            result.setMessage("实名失败");
            return result;

        }
        result.setCode(500);
        result.setMessage("实名失败");
        return result;
    }

    @Override
    public Result<List<String>> getBankList() throws Exception {
        Result<List<String>> result = new Result();
        List<XgbBank> banks = xgbBankMapper.selectList(new QueryWrapper<XgbBank>());
        List<String> list = new ArrayList<>();
        for (XgbBank xgbBank : banks) {
            list.add(xgbBank.getBankName());
        }
        result.setCode(200);
        result.setData(list);
        return result;
    }

    @Override
    public Result<List<XgbUserBank>> getUserBank(Long userId, String token) throws Exception {
        log.info("userId={},token={}", userId, token);
        Result<List<XgbUserBank>> result = new Result();
        if (loginVerification(userId, token)) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        List<XgbUserBank> list = xgbUserBankMapper.selectList(new QueryWrapper<XgbUserBank>()
                .eq("user_id", userId));
        for (XgbUserBank xgbUserBank : list) {
            XgbBank xgbBank = xgbBankMapper.selectOne(new QueryWrapper<XgbBank>()
                    .eq("bank_name", xgbUserBank.getOpenBank()));
            xgbUserBank.setBankImg(xgbBank.getBankImg());
            xgbUserBank.setCardNumber(xgbUserBank.getCardNumber().substring(xgbUserBank.getCardNumber().length() - 4));
        }

        result.setData(list);
        result.setCode(200);
        return result;
    }

    @Override
    public Result UnBundlingBank(Long userId, String token, String id) throws Exception {
        log.info("userId={},token={},id={}", userId, token, id);
        Result<List<XgbUserBank>> result = new Result();
        if (loginVerification(userId, token)) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        int row = xgbUserBankMapper.delete(new QueryWrapper<XgbUserBank>()
                .eq("id", id));
        if (row != 1) {
            result.setCode(500);
            result.setMessage("解绑失败");
            return result;
        }
        result.setCode(200);
        result.setMessage("解绑成功");
        return result;
    }

    @Override
    public Result bundlingBank(Long userId, String token, String openBank, String cardholder, String cardNumber, String openBranchBank, String mobile) {
        log.info("userId={},token={},openBank={},cardholder={},cardNumber={},openBranchBank={},mobile={}", userId, token, openBank, cardholder, cardNumber, openBranchBank, mobile);
        Result<List<XgbUserBank>> result = new Result();
        if (loginVerification(userId, token)) {
            result.setCode(401);
            result.setMessage("请登录");
            return result;
        }
        if (StringUtils.isEmpty(openBank)) {
            result.setCode(500);
            result.setMessage("开户行不能为空");
            return result;
        }
        if (StringUtils.isEmpty(cardholder)) {
            result.setCode(500);
            result.setMessage("持卡人不能为空");
            return result;
        }
        if (StringUtils.isEmpty(cardNumber)) {
            result.setCode(500);
            result.setMessage("卡号不能为空");
            return result;
        }
        if (StringUtils.isEmpty(openBranchBank)) {
            result.setCode(500);
            result.setMessage("开户支行不能为空");
            return result;
        }
        if (StringUtils.isEmpty(mobile)) {
            result.setCode(500);
            result.setMessage("手机号不能为空");
            return result;
        }
        XgbUserBank xgbUserBank = new XgbUserBank();
        xgbUserBank.setUserId(userId);
        xgbUserBank.setOpenBank(openBank);
        xgbUserBank.setCardholder(cardholder);
        xgbUserBank.setCardNumber(cardNumber);
        xgbUserBank.setOpenBranchBank(openBranchBank);
        xgbUserBank.setMobile(mobile);

        int row = xgbUserBankMapper.insert(xgbUserBank);
        if (row != 1) {
            result.setCode(500);
            result.setMessage("绑定失败");
            return result;
        }
        result.setCode(200);
        result.setMessage("绑定成功");
        return result;
    }

    @Scheduled(cron = "0 0 0 * * ?")
    public void reset() {
        int row = mapper.update(null, new UpdateWrapper<XgbUsers>()
                .set("today_order_num", 0));
        log.info("重置抢购次数:" + row);
    }

    private String createInviteCode() {
        String newInviteCode = RandomStringUtils.randomAlphanumeric(6).toUpperCase();
        QueryWrapper<XgbUsers> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("inv_code", newInviteCode);
        XgbUsers users = mapper.selectOne(queryWrapper);
        if (users != null) {
            return createInviteCode();
        }
        return newInviteCode;
    }

    public String makeToken() {
        String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte md5[] = md.digest(token.getBytes());
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(md5);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }


    private boolean loginVerification(Long userId, String token) {
        String redisToken = redisTemplate.opsForValue().get("token:" + userId);
        return (StringUtils.isEmpty(redisToken) || !redisToken.equalsIgnoreCase(token));
    }


    /**
     * 合并图片
     *
     * @param buffImg
     * @param waterImg
     * @param x
     * @param y
     * @param alpha
     * @return
     * @throws IOException
     */
    private static BufferedImage overlyingImage(BufferedImage buffImg, BufferedImage waterImg, int x, int y, float alpha) throws IOException {

        // 创建Graphics2D对象，用在底图对象上绘图
        Graphics2D g2d = buffImg.createGraphics();
        int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
        int waterImgHeight = waterImg.getHeight();// 获取层图的高度
        // 在图形和图像中实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 绘制
        g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
        g2d.dispose();// 释放图形上下文使用的系统资源
        return buffImg;
    }


    /**
     * 拼接文字
     *
     * @param content
     * @param ImageNew
     */
    private static void drawProductText(String content, BufferedImage ImageNew) {
        Graphics g = ImageNew.getGraphics();
        Font f = new Font("", Font.BOLD, 35);
        g.setColor(Color.decode("#ffffff"));
        g.setFont(f);
        g.drawString(content, 300, 1100);
        g.dispose();
    }

    /**
     * 将图片输出到磁盘
     *
     * @param buffImg
     * @param savePath
     */
    private static void generateSaveFile(BufferedImage buffImg, String savePath) {
        int temp = savePath.lastIndexOf(".") + 1;
        try {
            File outFile = new File(savePath);
            if (!outFile.exists()) {
                outFile.createNewFile();
            }
            ImageIO.write(buffImg, savePath.substring(temp), outFile);
            System.out.println("ImageIO write...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 转为BufferedImage
     *
     * @param fileUrl
     * @return
     * @throws IOException
     */
    private static BufferedImage getBufferedImage(String fileUrl) throws IOException {
        File file = new File(fileUrl);
        return ImageIO.read(file);
    }

    /**
     * 去掉二维码白边
     *
     * @param matrix
     * @return
     */
    private static BitMatrix deleteWhite(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + 1;
        int resHeight = rec[3] + 1;

        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1]))
                    resMatrix.set(i, j);
            }
        }
        return resMatrix;
    }
}
